#ifndef FRONTEND
#include "postgres.h"
#else
#include "postgres_fe.h"
#endif

#include "common/cryptohash.h"
#include "common/fdb_sm3.h"


#ifdef FDDGM

/* 将二进制（32字节）转换为字符串（64字节） */
static void fc_sha_bytes_to_hex64(uint8 fc_b[32], char* fc_s)
{
    static const char* fc_hex = "0123456789abcdef";
    int fc_q = 0;
    int fc_w = 0;

    for (fc_q = 0, fc_w = 0; fc_q < 32; fc_q++) {
        fc_s[fc_w++] = fc_hex[(fc_b[fc_q] >> 4) & 0x0F];
        fc_s[fc_w++] = fc_hex[fc_b[fc_q] & 0x0F];
    }
    fc_s[fc_w] = '\0';
}

bool fdb_sm3_hash(const void *fc_buff, size_t fc_len, char *fc_hexsum, const char **fc_errstr)
{

	uint8		fc_sum[SM3_DIGEST_LENGTH];
	pg_cryptohash_ctx *fc_ctx;

	*fc_errstr = NULL;
	fc_ctx = pg_cryptohash_create(PG_SM3);
	if (fc_ctx == NULL)
	{
		*fc_errstr = pg_cryptohash_error(NULL);
		return false;
	}

	if (pg_cryptohash_init(fc_ctx) < 0 ||
		pg_cryptohash_update(fc_ctx, fc_buff, fc_len) < 0 ||
		pg_cryptohash_final(fc_ctx, fc_sum, sizeof(fc_sum)) < 0)
	{
		*fc_errstr = pg_cryptohash_error(fc_ctx);
		pg_cryptohash_free(fc_ctx);
		return false;
	}

	fc_sha_bytes_to_hex64(fc_sum, fc_hexsum);
	pg_cryptohash_free(fc_ctx);
    
	return true;
}

/*
* sm3加密函数
*/
bool fdb_sm3_encrypt(const char *fc_passwd, const char *fc_salt, size_t fc_salt_len,
			   char *fc_buf, const char **fc_errstr)
{
	bool		fc_ret = false;
	size_t		fc_passwd_len = strlen(fc_passwd);
	/* 这里的 +1 只是为了避免不可移植的 malloc(0) 风险 */
	char	   *fc_crypt_buf = malloc(fc_passwd_len + fc_salt_len + 1);

	if (!fc_crypt_buf)
	{
		*fc_errstr = _("out of memory");
		return false;
	}

	/*
	 * 将盐放在最后，因为它可能被尝试破解
	 * SM3 输出的用户所知道。
	 */
	memcpy(fc_crypt_buf, fc_passwd, fc_passwd_len);
	memcpy(fc_crypt_buf + fc_passwd_len, fc_salt, fc_salt_len);

	strcpy(fc_buf, "SM3");
	fc_ret = fdb_sm3_hash(fc_crypt_buf, fc_passwd_len + fc_salt_len, fc_buf + SM3_LENGTH, fc_errstr);

	free(fc_crypt_buf);

	return fc_ret;
}

#endif